using System;
using UnityEngine;
using GameFramework;

namespace LS.SVariable
{
    public abstract class SavingAssociatedVariable : Variable
    {
        public event Action<SavingAssociatedVariable, object, object> OnRowValueChanged;

        protected string m_Name;
        protected string m_SaveGroupName;

        public string Name
        {
            get { return m_Name; }

            internal set { m_Name = value; }
        }

        public string SaveGroupName
        {
            get { return m_SaveGroupName; }

            internal set { m_SaveGroupName = value; }
        }

        public abstract object RowValue { get; set; }

        /// <summary>
        /// 初始化变量的新实例。
        /// </summary>
        public SavingAssociatedVariable()
        {
        }
        
        public virtual void Initialize(string savingGroupName, string name, object value = null)
        {
            if (!string.IsNullOrEmpty(this.Name) || !string.IsNullOrEmpty(this.SaveGroupName))
            {
                Debug.LogError($"Variable already initialized. Can not Initialize with {{name: {name}, savingGroup: {savingGroupName}}}.");
                return;
            }
            Name = name;
            SaveGroupName = savingGroupName;
            OnRowValueChanged += SetupSavingWhenValueChanged;
        }

        /// <summary>
        /// 清理变量值。
        /// </summary>
        public override void Clear()
        {
            m_Name = null;
            m_SaveGroupName = null;
            OnRowValueChanged = null;
        }

        /// <summary>
        /// 获取变量字符串。
        /// </summary>
        /// <returns>变量字符串。</returns>
        public override string ToString()
        {
            return (RowValue != null) ? RowValue.ToString() : "<Null>";
        }

        protected virtual void SendValueChangedEvent(object previous, object newValue)
        {
            OnRowValueChanged?.Invoke(this, previous, newValue);
        }

        public abstract void SetValueWithoutNotification(object value);

        private static void SetupSavingWhenValueChanged(SavingAssociatedVariable variable, object previousValue, object newValue)
        {
            if(string.IsNullOrEmpty(variable.Name) || string.IsNullOrEmpty(variable.SaveGroupName))
                return;
            
            LSEntry.Saving.SetObject(variable.SaveGroupName, variable.Name, newValue);
        }
    }

    public abstract class SavingAssociatedVariable<T> : SavingAssociatedVariable
    {
        public event Action<SavingAssociatedVariable<T>, T, T> OnValueChanged;

        protected T m_Value;

        public override object RowValue
        {
            get { return Value; }
            set { Value = (T)value; }
        }

        /// <summary>
        /// 初始化变量的新实例。
        /// </summary>
        public SavingAssociatedVariable() : base()
        {
            m_Value = default(T);
        }

        /// <summary>
        /// 获取变量类型。
        /// </summary>
        public override Type Type
        {
            get { return typeof(T); }
        }

        /// <summary>
        /// 获取或设置变量值。
        /// </summary>
        public T Value
        {
            get { return m_Value; }

            set { SetValue(value); }
        }

        /// <summary>
        /// 获取变量值。
        /// </summary>
        /// <returns>变量值。</returns>
        public override object GetValue()
        {
            return m_Value;
        }

        /// <summary>
        /// 设置变量值。
        /// </summary>
        /// <param name="value">变量值。</param>
        public override void SetValue(object value)
        {
            SetValue((T)value);
        }

        public void SetValue(T value)
        {
            if (m_Value != null && value != null)
            {
                if (m_Value.Equals(value))
                    return;
            }
            else if (m_Value == null && value == null)
            {
                return;
            }

            T previous = m_Value;
            m_Value = value;
            this.SendValueChangedEvent(previous, value);
        }

        public override void SetValueWithoutNotification(object value)
        {
            SetValueWithoutNotification((T)value);
        }

        public void SetValueWithoutNotification(T value)
        {
            m_Value = value;
        }

        /// <summary>
        /// 清理变量值。
        /// </summary>
        public override void Clear()
        {
            m_Value = default(T);
            OnValueChanged = null;
            base.Clear();
        }

        protected void SendValueChangedEvent(T previous, T newValue)
        {
            OnValueChanged?.Invoke(this, previous, m_Value);
            base.SendValueChangedEvent(previous, newValue);
        }
    }
}